import { history } from 'umi';
import queryString from 'query-string';
import isUndefined from 'lodash/isUndefined';
import isFunction from 'lodash/isFunction';
import type { KeyObj } from '@/constants';
import type { PluginCtx } from 'sula/es/types/ctx';
import type { FormInstance } from 'sula/es/form/index';
import type { TableInstance } from 'sula/es/table/index';
import type { ParsedQuery } from 'query-string';

export function generateRouterOptions(config: any) {
  const { query, search, path } = config;
  if (isUndefined(query) && isUndefined(search)) {
    return path;
  }

  const finalSearch = search || `?${queryString.stringify(query)}`;

  return {
    pathname: path,
    search: finalSearch,
  };
}

export const replace = (ctx: PluginCtx, config: any) => {
  ctx.history.replace(generateRouterOptions(config));
};
type RouteReplaceRspToQueryConfigArgs = {
  pickQuery?: string[]; // 从上下文result.$submit中选出需要拼接到Url后的参数字段
  formRef?: React.RefObject<FormInstance>; // 若传入filter方法和form实例，会调用setFieldsValue自动将filter方法返回的对象填充入表单
  tableRef?: React.RefObject<TableInstance>; // 若传入filter方法和table实例，会调用setFilters自动将filter方法返回的对象填充入表格筛选参数
  filter?: (query: ParsedQuery) => any; // 传入参数为router变更后最新的history.location.query对象
};
type RouteReplaceRspToQueryConfig = {
  type: string;
  args: RouteReplaceRspToQueryConfigArgs;
};
export const routeReplaceRspToQuery = (ctx: PluginCtx, config: RouteReplaceRspToQueryConfig) => {
  const { result } = ctx;
  if (!(result && result.$submit)) {
    return;
  }
  let query = result.$submit;
  if (config.args.pickQuery && Array.isArray(config.args.pickQuery)) {
    query = config.args.pickQuery.reduce((pickQuery: KeyObj, key: string) => {
      return Object.assign(pickQuery, { [key]: query[key] });
    }, {});
  }
  replace(ctx, { query: { ...query } });
  if (config.args.filter && isFunction(config.args.filter)) {
    const filter = config.args.filter(history.location.query);
    if (config.args.formRef && config.args.formRef.current) {
      const { setFieldsValue } = config.args.formRef.current;
      setFieldsValue(filter);
    }
    if (config.args.tableRef && config.args.tableRef.current) {
      const { setFilters } = config.args.tableRef.current;
      setFilters(filter);
    }
  }
};
